/*
 * Simple test file for cxxomfort
 * When compiled and run, this will show
 * how to use explicit_cast<>.
 *
 * This and other examples assume cxxomfort is installed in
 * include library path; if otherwise, compile with
 * -I /path/to/cxxomfort .
 */

#include <cxxomfort/base.hpp>
#include <cxxomfort/string.hpp>
#include <iostream>
#include <string>

struct mybar {
    mybar (int x)
    : v(x) {++z;}

    int v;
    static int z;
};

int mybar::z= 0;

struct myfoo {
    myfoo (unsigned x) : foo(x) {}

    CXXO_EXPLICIT_OPERATOR(bool) () const {
        bool b = true;
        return b;
    }
    CXXO_EXPLICIT_OPERATOR(std::string) () const {
        return std::string(foo, 'x');
    }
    CXXO_EXPLICIT_OPERATOR(mybar) () const {
        return mybar(static_cast<int>(foo));
    }

    private:
    unsigned foo;
};

void dobar (mybar const& b) {
    using namespace std;
    cout<< b.v<< ","<< b.z<< endl;
}

int doint (myfoo const& f) {
    return explicit_cast<bool>(f);
}

int main () {
    using namespace std;
    cxxomfort::output_info(); cout<< endl;
    myfoo foo1(4);
    myfoo foo2(7);
    mybar bar1(2);
    mybar bar2(4);
    //long z1 = explicit_cast<bool>(foo2); (void)z1; // should not compile since we only want explicit things
    //long z2 = static_cast<bool>(foo2); (void)z2; // this works only in C++11
    cout<< "Should show "<< bar1.v<< ",x :"<< endl;
    dobar(bar1);
    cout<< "Should show "<< bar2.v<< ",x :"<< endl;
    dobar(bar2);
    cout<< "Should show an integer: "
    << doint(foo2)<< endl;
    //dobar(foo2); // <-- should fail
    cout<< "Should show the var of foo2:"<< endl;
    dobar( explicit_cast<mybar>(foo2)); // <-- should work
    string str0 = "0";
    cout<< str0<< endl;
    string str1 = explicit_cast<string>(foo1);
    //string str2 = foo1; // <-- should fail
    cout<< str1<< endl;

}
